/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2007 Ben Motmans <ben.motmans@gmail.com>
 * Copyright (C) 2007 Philippe Durand <draekz@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Collections.Generic;

using G=Gtk;
using Gtk;
using Glade;

using Anculus.Core;
using Anculus.Gui;

using Galaxium.Core;
using Galaxium.Client;
using Galaxium.Protocol;
using Galaxium.Protocol.Gui;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

namespace Galaxium.Protocol.Irc.GtkGui
{
	public class IrcAccountWidget : BasicAccountWidget
	{
		private Entry _displayNameEntry;
		private HBox _serverBox;
		private Button _manageServersButton;
		private ComboBox _serversCombo;
		private IConfigurationSection _config = Configuration.Protocol.Section["IRC"];
		private Dictionary<string, int> _networkLookup = new Dictionary<string, int> ();
		
		public IrcAccountWidget () : base (IrcProtocol.Instance)
		{
			_manageServersButton = new G.Button ();
			_manageServersButton.Image = new G.Image (IconUtility.GetIcon ("galaxium-server", IconSizes.Small));
			
			_displayNameEntry = new G.Entry ();
			
			_serversCombo = ComboBox.NewText ();
			
			_serverBox = new G.HBox ();
			_serverBox.PackStart (_serversCombo, true, true, 0);
			_serverBox.PackStart (_manageServersButton, false, true, 0);
		}
		
		public override void Initialize ()
		{
			// There are some widgets we do not want in this one.
			//OmitPresenceCombo = true;
			PasswordRequired = false;
			
			_presenceCombo = CreateStatusCombo (IrcPresence.Online, //the selected one
					IrcPresence.Online, IrcPresence.Away);
			
			AddCustomAccountItem ("Nick:", _displayNameEntry);
			AddCustomAccountItem ("Server:", _serverBox);
			
			LoadNetworkInfo ();
			
			base.Initialize ();
			
			_manageServersButton.Clicked += ManageButtonClicked;
			_displayNameEntry.Changed += DisplayNameChanged;
			_serversCombo.Changed += new EventHandler (ServerChanged);
			//_serversCombo.Entry.EditingDone += new EventHandler (ServerEditingDone);
			
			_accountCombo.Entry.TooltipText = "Provide a name to use in identifying this IRC account. Example: My IRC Account";
		}
		
		protected override IAccount SetAccount ()
		{
			IrcAccount account = GetAccount(_accountCombo.Entry.Text) as IrcAccount;
			
			if (account != null)
			{
				account.Password = _passwordEntry.Text;
				account.AutoConnect = _autoconnectCheck.Active;
				account.RememberPassword = _rememberPassCheck.Active;
				account.DisplayName = _displayNameEntry.Text;
				account.ConnectionInfo = GetConnectionInfo (_serversCombo.ActiveText); 
				account.InitialPresence = GetInitialPresence ();
				
				return account;
			}
			else
			{
				IrcConnectionInfo connectionInfo = GetConnectionInfo (_serversCombo.ActiveText);
				IrcAccount newAccount = new IrcAccount (_accountCombo.Entry.Text, connectionInfo, _passwordEntry.Text, _displayNameEntry.Text, _autoconnectCheck.Active, _rememberPassCheck.Active);
				newAccount.InitialPresence = GetInitialPresence ();
				AccountUtility.AddAccount (newAccount);
				
				return newAccount;
			}
		}
		
		protected override void AccountNameChanged (object sender, EventArgs args)
		{
			base.AccountNameChanged (sender, args);
			
			_connectButton.Sensitive = CheckInput ();
		}
		
		protected override void LoadAccountInfo ()
		{
			base.LoadAccountInfo ();
			
			IrcAccount account = Account as IrcAccount;
			
			if (account != null)
			{
				_displayNameEntry.Text = account.DisplayName;
				_serversCombo.Active = _networkLookup[account.ConnectionInfo.Network];
			}
		}
		
		private void LoadNetworkInfo ()
		{
			IList<IrcNetworkInfo> networks = null;
			string active_network = String.Empty;
			
			if (_serversCombo.ActiveText != null)
				active_network = _serversCombo.ActiveText;
			
			if (_config.ContainsKey ("Networks"))
				networks = _config.GetList<IrcNetworkInfo> ("Networks");
			else
			{
				List<IrcNetworkInfo> stored = new List<IrcNetworkInfo> (IrcProtocolHelper.GetAllStoredNetworkInfo ());
				
				stored.Sort ();
				
				networks = stored;
				
				_config.SetList<IrcNetworkInfo> ("Networks", networks);
			}
			
			for (int i = _networkLookup.Count - 1; i >= 0; i--)
				_serversCombo.RemoveText (i);
			
			_networkLookup.Clear();
			
			int count = 0;
			
			foreach (IrcNetworkInfo info in networks)
			{
				_networkLookup.Add (info.Name, count++);
				
				_serversCombo.AppendText (info.Name);
			}
			
			if (active_network != String.Empty)
			{
				if (_networkLookup.ContainsKey (active_network))
					_serversCombo.Active = _networkLookup[active_network];
				else
					_serversCombo.Active = 0;
			}
			else
			{
				TreeIter iter;
				
				if (_serversCombo.Model.GetIterFirst (out iter))
					_serversCombo.SetActiveIter (iter);
			}
		}
		
		private IrcConnectionInfo GetConnectionInfo (string network)
		{
			IList<IrcNetworkInfo> networks = _config.GetList<IrcNetworkInfo> ("Networks");
			IrcNetworkInfo info = Sort.BinarySearch<IrcNetworkInfo, string> (networks, new IrcNetworkInfoNameComparer (), network);
			
			return new IrcConnectionInfo (info);
		}
		
		public override void EnableFields ()
		{
			base.EnableFields ();
			
			SetFields (true);
		}
		
		public override void DisableFields (bool omit_cancel)
		{
			base.DisableFields (omit_cancel);
			
			SetFields (false);
		}
		
		private void SetFields (bool flag)
		{
			_displayNameEntry.Sensitive = flag;
			_serversCombo.Sensitive = flag;
			_manageServersButton.Sensitive = flag;
		}
		
		protected override string PresenceTextLookup (IPresence item)
		{
			return item.State;
		}
		
		protected override Gdk.Pixbuf PresenceImageLookup (IPresence item, IIconSize size)
		{
			return IconUtility.StatusLookup (item, size);
		}
		
		protected override void ConnectButtonClicked (object sender, EventArgs args)
		{
			_current_session = CreateSession () as IrcSession;
			
			if (_current_session == null) //the selected account is in use
				return;
			
			base.ConnectButtonClicked (sender, args);
		}
		
		protected override void SettingsButtonClicked (object sender, EventArgs args)
		{
			
		}
		
		private void ManageButtonClicked (object sender, EventArgs args)
		{
			ManageNetworksDialog dialog = new ManageNetworksDialog (_serversCombo.ActiveText);
			
			dialog.Run ();
			dialog.Destroy ();
			
			LoadNetworkInfo ();
		}
		
		private void DisplayNameChanged (object sender, EventArgs args)
		{
			_connectButton.Sensitive = CheckInput ();
		}
		
		private void ServerChanged (object sender, EventArgs args)
		{
			_connectButton.Sensitive = CheckInput ();
		}
	
	// CHECKTHIS
	//	
	//	private void PortChanged (object sender, EventArgs args)
	//	{
	//		_connectButton.Sensitive = CheckInput ();
	//	}
		
		protected override bool CheckInput ()
		{
			if (_displayNameEntry.Text.Length == 0)
				return false;
			
			if (_serversCombo.ActiveText == null)
				return false;
			
			if (_serversCombo.ActiveText.Length == 0)
				return false;
			
			return base.CheckInput();
		}
	}
}